/**
* @Author:		Nguyen Duy	<tratstil@gmail.com>
* 2011 - For a Profession Style
*/
#include "stdafx.h"
#include "tester.h"
#include <string.h>
#include <stdarg.h>
//extern char* _ResourceFileName[];
//extern int _IDtoFileName[];
//extern int _ResourceInfo[];
#if TESTER
Tester* Tester::_this = NULL;
bool tester_mod_menu_open;
RectStream Tester::_Trec_ctrl_button = {RECTSTREAM_INIT(0, 0, GAME_DESIGN_HEIGHT - TBUTTON_H, 50, TBUTTON_H)};
RectStream Tester::_Trec_mod_ctrl = {RECTSTREAM_INIT(0,50, GAME_DESIGN_HEIGHT - TBUTTON_H, TBUTTON_W,TBUTTON_H)};
TextButtonStream* Tester::_Trec_mods = NULL;
int Tester::GetFontHeight(CSprite* spr)
{
	return(spr->_module_h[0]&0xFFFF)+ spr->_line_spacing;
}
Tester::Tester()
{
	InitTester();
}

Tester* Tester::GetTesterInstance()
{
	if(_this != NULL)
	{
		return _this;
	}
	_this = new Tester();
	return _this;
}

void Tester::InitTester()
{
	tfisrtrun = true;
	//_input_stream = new ResourceInputStream();
	/*<init feature>*/
		for(int i = 0 ;i<TFEATURE_NUM;i++)
		{
			TFEATURE_LOCK[i] = false;
		}
		TFEATURE_LOCK[TFLOG] = !TF_DEF_LOG;
    
    RectStream rec_ctrl = {RECTSTREAM_INIT(0,GX(0),GY(GAME_DESIGN_HEIGHT - TBUTTON_H), G(GAME_DESIGN_WIDTH), G(TBUTTON_H))};
    _Trec_ctrl = rec_ctrl;
    
		InitTLog();
	/*</init feature>*/
	/*<init some thing else>*/
		tangle =0;
		tester_mod_menu_open = false;
	/*</init some thing else>*/
	/*<add module>*/
		_Tpage = true;
		for(int i = 0; i< TESTER_MODULE_LENGTH; i ++)
		{
			tb_mInUse[i] = false;
		}
		ti_mActive = -1;	
		ti_mNum = 0;
	/*</add module>*/
}
void Tester::Run()
{
	if(tfisrtrun)
	{
		//SAFE_DEL(_g);
		_g = Game->_g;
		/*<load font>*/
		Game->LoadSprite(GFX_TESTER_FONT_YELLOW);
		Game->LoadSprite(GFX_TESTER_FONT_RED);
		Game->LoadSprite(GFX_TESTER_FONT_WHITE);
		Game->LoadSprite(GFX_TESTER_FONT_SOFTGREEN);
		fyellow = Game->GetSprite(GFX_TESTER_FONT_YELLOW);
		fgreen = Game->GetSprite(GFX_TESTER_FONT_SOFTGREEN);
		fwhite = Game->GetSprite(GFX_TESTER_FONT_WHITE);
		fred = Game->GetSprite(GFX_TESTER_FONT_RED);
		fyellow->_char_spacing = 1;
		fwhite->_char_spacing = 1;
		fred->_char_spacing = 1;
		/*</load font>*/

	//	InitObjective();
#if TEST_THREAD_ACHI
		AddTestModule(new ctmAchievement());
#endif
	//	AddTestModule(new ctmSurvival()); 

#if TEST_THREAD_SMETER
		//speedmeter_module_id = AddTestModule(new ctmSpeedMeter());
		SpeedMeterObject = new ctmSpeedMeter();
		AddTestModule(SpeedMeterObject);
#endif

        Game->correctGameSizeOfStream(0, 1, (char*) &_Trec_ctrl_button);
        Game->correctGameSizeOfStream(0, 1, (char*) &_Trec_mod_ctrl);
        
        _Trec_mods = new TextButtonStream[ti_mNum];
        for(int i = 0; i< ti_mNum; i++){
            TextButtonStream tmp = {"", -1,RECTSTREAM_INIT(i, _Trec_mod_ctrl.getX(), (_Trec_mod_ctrl.getY() - ((i+1)*G(TBUTTON_H))), G(TBUTTON_W), G(TBUTTON_H))};
            int len = getStringLen(tModule[i]->name);
            MEMCOPY(tModule[i]->name,tmp.Title,len);
            tmp.Title[len] = '\0';
            _Trec_mods[i] = tmp;
        }
		tfisrtrun = false;
#if defined(USE_SOCIAL_NETWORK) && defined(USE_CPAGE)
		TestSocialPage = new tPageScocial();
		Game->addPage((CPage*)TestSocialPage);
#endif
		return;
	}
	UpdateTester();
	RenderTester();
	Game->_g->Flush2D();
}
void Tester::ResetTester()
{
	tangle = 0;
}
void Tester::UpdateTester()
{
	if(_Tpage)
	{
		tangle += 0.01f;
		if(tangle>3.6f)
		{
			tangle = 0;
		}
		UpdateTLog();

		if(ti_mActive>-1 && tb_mInUse[ti_mActive])
		{
			tModule[ti_mActive]->UpdateTestModule();
		}
	}
}
void Tester::RenderTester()
{
#if TEST_MODE
	_g->SetColor(TEST_BG_COLOR);
	_g->FillRect(0,0,TSCR_W,TSCR_H,true);
#endif
	char cdata[100];
	if(_Tpage)
	{
		sprintf(cdata,"-");
		fgreen->DrawAnsiText(_g,_Trec_ctrl_button.getCenterX(),_Trec_ctrl_button.getCenterY(),_HCENTER,cdata);

		sprintf(cdata,"mod");

		//module menu
        
		if(tester_mod_menu_open)
		{
            fyellow->DrawAnsiText(_g,_Trec_mod_ctrl.getCenterX(),_Trec_mod_ctrl.getCenterY(),_HCENTER,cdata);
			for(int i = 0;i<ti_mNum;i++)
			{
                if(_Trec_mods[i].State == -1){
					fgreen->DrawAnsiTextFormat(_g,_Trec_mods[i].Rect.getX(),_Trec_mods[i].Rect.getY(),_LEFT,"%s",_Trec_mods[i].Title);
				}
				else
				{
					fyellow->DrawAnsiTextFormat(_g,_Trec_mods[i].Rect.getX(),_Trec_mods[i].Rect.getY(),_LEFT,"%s",_Trec_mods[i].Title);
				}
			}
		}else{
            fgreen->DrawAnsiText(_g,_Trec_mod_ctrl.getCenterX(),_Trec_mod_ctrl.getCenterY(),_HCENTER,cdata);
        }

		//feature
        int feature_x = _Trec_mod_ctrl.getX() + _Trec_mod_ctrl.getWidth();
        int feature_w = _Trec_ctrl.getX() + _Trec_ctrl.getWidth() - feature_x;
		
		if(TFEATURE_NUM > 0)
		{
			int btw = feature_w/TFEATURE_NUM;
			for(int i=0;i<TFEATURE_NUM;i++)
			{
				sprintf(cdata,fName[i]);
				if(IsFeatureLock(i))
				{
					fyellow->DrawAnsiText(_g,feature_x + i*btw,_Trec_ctrl.getY(),_LEFT,cdata);
				}
				else
				{
					fgreen->DrawAnsiText(_g,feature_x + i*btw,_Trec_ctrl.getY(),_LEFT,cdata);
				}
			}
		}
	}
	else
	{
		//ctemp.Fill(_g);
		//ctemp.HighLight(_g);
		sprintf(cdata,"+");
		fgreen->DrawAnsiText(_g,_Trec_ctrl_button.getCenterX(),_Trec_ctrl_button.getCenterY(),_HCENTER,cdata);
	}

	if(_Tpage)
	{		
		if(ti_mActive>-1 && tb_mInUse[ti_mActive])
		{
			tModule[ti_mActive]->RenderTestModule();
		}
		RenderTLog();
	}
}
void Tester::UpdateTouch()
{
    if(tester_mod_menu_open){
        Game->CheckTouchOnStream(ti_mNum, _Trec_mods);
        for(int i = 0; i< ti_mNum; i++){
            if(_Trec_mods[i].State == TOUCH_UP){
                ti_mActive = i;
                break;
            }
        }
    }
	for(int i = 0; i < Game->_num_touches; i++){
		if(Game->_touches[i]->_flag){
			int x = Game->_touches[i] ->x;
			int y = Game->_touches[i] ->y;
			int type = Game->_touches[i] ->_state;
			if(type == TOUCH_UP){
                if(Game->CheckPointOnStream(1, &_Trec_ctrl_button, (float)x, (float)y) > -1){
                    _Tpage = !_Tpage;
                }
                if(!_Tpage){
					Game->_touches[i]->_flag = false;
					return;
				}
				bool use_touch = false;
                if(Game->CheckPointOnStream(1, &_Trec_mod_ctrl, x, y) > -1){
                    tester_mod_menu_open = !tester_mod_menu_open;
					use_touch = true;
                }
				//feature
                int feature_x = _Trec_mod_ctrl.getX() + _Trec_mod_ctrl.getWidth();
                int feature_w = _Trec_ctrl.getX() + _Trec_ctrl.getWidth() - feature_x;
                
				if(x > feature_x && x < feature_w && y > _Trec_ctrl.getY() && y < _Trec_ctrl.getY() + _Trec_ctrl.getHeight())
				{
					if(TFEATURE_NUM > 0)
					{
						int tx = x - int(feature_x);
						int btw = feature_w/TFEATURE_NUM;
						int num = tx/btw;
						if(tx%btw >0)num++;
						if(num <= TFEATURE_NUM)
						{
							TFEATURE_LOCK[num - 1] = !TFEATURE_LOCK[num - 1];
						}
					}
					use_touch = true;
				}
				if(use_touch){
					Game->_touches[i]->_flag = false;
					continue;
				}
			}
			bool use_touch = false;
			use_touch |= UpdateTouchTLog(x,y,type);
			if(ti_mActive>-1 && tb_mInUse[ti_mActive])
			{
				use_touch |= tModule[ti_mActive]->UpdateTouchTestModule(x,y,type);
			}
			if(use_touch){
					Game->_touches[i]->_flag = false;
			}
		//#if TEST_MODE
		}
	}
}
void Tester::tLockFeature(int Feature)
{
	TFEATURE_LOCK[Feature] = true;
}
void Tester::tUnLockFeature(int Feature)
{
	TFEATURE_LOCK[Feature] = false;
}

/*<work with module>*/
	int Tester::AddTestModule(TestModule* ctModule)
	{
		if(ti_mNum < TESTER_MODULE_LENGTH)
		{
			tModule[ti_mNum] = ctModule;
			tb_mInUse[ti_mNum] = true;
			ctModule->InitTestModule();
			ti_mNum++;
			return ti_mNum-1;
		}
		return -1;
	}
/*</work with module>*/
/*
void Tester::LoadSprite(CSprite* sprite,int sprite_id, bool is_cache_texture, bool linear_texture, int pal, bool load_trueColor_texture)
{
	GetResourceInputStream(sprite_id);
	sprite->Load(_input_stream, is_cache_texture, linear_texture, pal, load_trueColor_texture);
	_input_stream->Close();
}

void Tester::LoadSprite(CSprite* sprite,int sprite_id, bool is_cache_texture, int pal)
{
	LoadSprite(sprite,sprite_id, is_cache_texture, true, pal);
}*/
/*ResourceInputStream* Tester::GetResourceInputStream(int iResID)
{
	const char* sFile = _ResourceFileName[_IDtoFileName[iResID]];
#ifdef MAC_OS
	sFile = GetRealFilePath(sFile);
#endif
	INT32 iOffset = _ResourceInfo[2*iResID];
	bool result = _input_stream->Open(sFile, iOffset);
	if (result)
	{
		return _input_stream;
	}	
	_input_stream->Close();
	delete sFile;
	return NULL;
}*/
#endif

#if TESTER
int tlog_opacity;
float tlog_zoom;
	void Tester::InitTLog()
	{
		tlog_opacity = TLOG_DEF_OPACITY;
		tlog_zoom = TLOG_DEF_ZOOM;
		sprintf(fName[TFLOG],"log");
		_cur_log = 0;
		_log_scrolly = 0;
		_Tlog_total_h = 0;
		_log_can_scroll = false;
		RectStream Tlog_rec = {RECTSTREAM_INIT(0,0,0,GAME_DESIGN_WIDTH/2,GAME_DESIGN_HEIGHT/4*3)};
		_Tlog_rec = Tlog_rec;
		Game->correctGameSizeOfStream(0,1,(char*) &_Tlog_rec);
        TlogClear();
	}
	void Tester::TLog(char* LogStr,int type)
	{	
		if(!TesterReady)
		{
			printf("Tlog:%s\n",LogStr);
			return;
		}
		int x = _Tlog_rec.getX();
		int y = _Tlog_rec.getY();
		int w = _Tlog_rec.getWidth();
		int h = _Tlog_rec.getHeight();

		int e = (_cur_log%TLOG_ELEMENT);
        if(_cur_log >= TLOG_ELEMENT)
		{
			_Tlog_total_h -= _Tlog_h[e];
		}
        
		int len = getStringLen(LogStr);
		if(len >= TLOG_LENGTH)len = TLOG_LENGTH -1;
		MEMCOPY(LogStr,&_Tlog[e][0],len);
		_Tlog[e][len] = '\0';

		int datai[1000];
		CSprite* font =((type==1)?fyellow:fwhite);
		font->CalcPage(datai,font->StringToUnichar(&_Tlog[e][0]), strlen(&_Tlog[e][0]),w - G(20));
		int lh = datai[0] * (GetFontHeight(fwhite)+2) * tlog_zoom;

		_Tlog_h[e] = lh;
		_Tlog_total_h += lh;
		_Ttype[e] = type;
		_cur_log++;
		
		if(_cur_log>1000)
		{
			TlogClear();
		}
	}
	void Tester::TLog(int type,const char* format, ...)
	{
		char cdata[TLOG_LENGTH];
		va_list arg_list;
		va_start(arg_list, format);
		vsprintf(cdata,format, arg_list);
		va_end(arg_list);
		TLog(cdata,type);
	}
	void Tester::RenderTLog(){
		if(IsFeatureLock(TFLOG) || !TesterReady)
		{			
			return;
		}
		//printf("render logsdfsdfasdfasdf===============================\n");
		if(_cur_log>0)
		{
			int x = _Tlog_rec.getX();
			int y = _Tlog_rec.getY();
			int w = _Tlog_rec.getWidth();
			int h = _Tlog_rec.getHeight();

            int mark = (_cur_log%TLOG_ELEMENT);
            
			_g->SetOpacity(tlog_opacity);
			_g->SetScale(tlog_zoom,tlog_zoom,x,y);
			_g->SetColor(0x55000000);
			_g->FillRect(x,y,w,h,true);
			
			int datai[1024];
			// draw control button
			if(_cur_log>0)
			{
				fwhite->DrawAnsiTextFormat(_g,x,y,_LEFT,"clear : %d",_cur_log);
			}
			_g->SetClip(x,y + G(TBUTTON_H),w,h - G(TBUTTON_H));
			// draw log record
			
			if(_cur_log < TLOG_ELEMENT) mark = _cur_log;
			float fheight = (GetFontHeight(fwhite)+2)*tlog_zoom;

			float log_y = y - _log_scrolly + G(TBUTTON_H);
			int count = 0;
            if(_cur_log >= TLOG_ELEMENT) count = _cur_log - TLOG_ELEMENT;
			char cdata[5];
			if(_cur_log >= TLOG_ELEMENT)
			{
				for(int j = mark;j < TLOG_ELEMENT;j++)
				{
					
					CSprite* font = fwhite;
                    if(_Ttype[j] == TLOG_TITLE)font = fyellow;
                    else if(_Ttype[j] == TLOG_ERROR)font = fred;
                    
                    sprintf(cdata,"%d",count + 1);
                    font->DrawAnsiText(_g,x,log_y,_LEFT,cdata);
					font->CalcPage(datai,font->StringToUnichar(&_Tlog[j][0]), strlen(&_Tlog[j][0]),w - G(TLOG_LEFT_WIDTH));
					if(log_y + fheight * datai[0] < y){
						log_y += fheight * datai[0];
						count++;
						continue;
					}
					font->DrawPage(_g,font->StringToUnichar(&_Tlog[j][0]),datai,strlen(&_Tlog[j][0]),x + G(TLOG_LEFT_WIDTH), log_y, _TOP | _LEFT);
					log_y += fheight * datai[0];
					count++;
				}
			}
			for(int j = 0;j<mark;j++)
			{
				CSprite* font = fwhite;
				if(_Ttype[j] == TLOG_TITLE)font = fyellow;
				else if(_Ttype[j] == TLOG_ERROR)font = fred;
                
                sprintf(cdata,"%d",count + 1);
				font->DrawAnsiText(_g,x,log_y,_LEFT,cdata);
				font->CalcPage(datai,font->StringToUnichar(&_Tlog[j][0]), strlen(&_Tlog[j][0]),w - G(TLOG_LEFT_WIDTH));
				if(log_y + fheight * datai[0] < y){
					log_y += fheight * datai[0];
					count++;
					continue;
				}
				font->DrawPage(_g,font->StringToUnichar(&_Tlog[j][0]),datai,strlen(&_Tlog[j][0]),x+ G(TLOG_LEFT_WIDTH), log_y, _TOP | _LEFT);
				log_y += fheight*datai[0];
				count++;
			}		
			_g->ClearClip();
			_g->ClearScale();
			_g->SetOpacity(100);
			
		}
	}
	void Tester::UpdateTLog()
	{
		if(IsFeatureLock(TFLOG))
		{
			return;
		}
		int x = _Tlog_rec.getX();
		int y = _Tlog_rec.getY();
		int w = _Tlog_rec.getWidth();
		int h = _Tlog_rec.getHeight();

		if(_Tlog_total_h < (h -  G(TBUTTON_H)))
		{
			_log_can_scroll = false;
			_log_scrolly = 0;
		}
		else
		{
			//_log_can_scroll = true;
			//float show_log_h = _Tlog_total_h;
			//if(_log_scrolly>0) _log_scrolly = 0;
			//if(_log_scrolly + show_log_h < y+h)
			_log_scrolly = (_Tlog_total_h - (h -  G(TBUTTON_H)));
		}
	}
	bool Tester::UpdateTouchTLog(int tx, int ty, int type)
	{
		if(IsFeatureLock(TFLOG))
		{
			return false;
		}
		int x = _Tlog_rec.getX();
		int y = _Tlog_rec.getY();
		int w = _Tlog_rec.getWidth();
		int h = _Tlog_rec.getHeight();

		if(Game->CheckPointOnStream(_Tlog_rec,tx,ty))
		{
			if(type == TOUCH_DOWN)
			{	
				_log_mousedown_y  = ty;
			}
			if(type == TOUCH_DRAG)
			{	
				if(CMath::ABSOLUTE_VALUE(ty - _log_mousedown_y)>= 2)
				{
					 _log_scrolly +=(ty - _log_mousedown_y);
					_log_mousedown_y = ty;
				}
			}
		}
		if(type == TOUCH_UP)
		{	
			if(tx>x && tx < x+ w && ty >y&& ty <y+ G(TBUTTON_H))
			{
				int btw = w / TLOG_BUTTON_NUM;
				int num = tx/btw;
				if(tx%btw > 0)num++;
				switch(num)
				{
				case 1:
					TlogClear();
                    return true;
					break;
				}
				
			}			
		}
        return false;
	}
	void Tester::TlogClear()
	{
		_cur_log = 0;
		_Tlog_total_h = 0;
        for(int i = 0; i< TLOG_ELEMENT; i++){
            _Tlog_h[i] = 0;
        }
	}

#if defined(USE_SOCIAL_NETWORK) && defined(USE_CPAGE)
void tPageScocial::init(){
	RectStream canvas = {RECTSTREAM_INIT(0,GX(GAME_DESIGN_WIDTH - 100),0,G(100),G(5))};
	setCanvas(canvas);
}
void tPageScocial::update(){
}
void tPageScocial::render(GLESLib* g){
	int w = Canvas.getWidth()/CSOCIAL_REQUEST_MAX_REQUEST;
	for(int i = 0; i< CSOCIAL_REQUEST_MAX_REQUEST; i++){
		if(CSocialNetwork::RequestsStatus[i]){
			g->SetColor(0xFFFF0000);
		}else{
			g->SetColor(0xFF000000);
		}
		g->FillRect(Canvas.getX() + i* w,Canvas.getY(),w,Canvas.getHeight());
		g->SetColor(0xFF00FFFF);
		g->DrawLine(Canvas.getX() + i* w,Canvas.getY(),Canvas.getX() + i* w,Canvas.getY() + Canvas.getHeight());
	}
}
bool tPageScocial::updateTouch(int x, int y, int type){
	return false;
}
void tPageScocial::release(){
}
void tPageScocial::setCanvas(RectStream canvas){
	Canvas = canvas;
}
#endif //USE_SOCIAL_NETWORK  USE_CPAGE

#endif//TESTER
